package cc.recent.normal.information.multi_engine;

import android.app.Activity;
import android.text.TextUtils;
import android.util.Log;

import java.util.HashMap;
import java.util.Map;

import cc.recent.normal.information.App;
import io.flutter.FlutterInjector;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineGroup;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.StandardMessageCodec;

import cc.recent.normal.information.multi_engine.Messages.CommonParams;

interface EngineBindingsDelegate {
    void openNativePage(Map<String, Object> args);
    String getInitialRoute();
    void pop(Map<String, Object> args);
}

public class EngineBindings {

    private static final String TAG = "EngineBindings";

    final private FlutterEngine engine;
    final private BasicMessageChannel<Object> mMessageChannel;
    final private Activity mActivity;
    final private EngineBindingsDelegate delegate;

    public EngineBindings(
            Activity context,
            EngineBindingsDelegate delegate,
            String entrypoint) {

        FlutterEngineGroup engines = ((App)App.getInstance()).engines;
        DartExecutor.DartEntrypoint dartEntrypoint = new DartExecutor.DartEntrypoint(
                FlutterInjector.instance().flutterLoader().findAppBundlePath(),
                entrypoint
        );
        mActivity = context;
        this.delegate = delegate;
        engine = engines.createAndRunEngine(context, dartEntrypoint);
        mMessageChannel =  new BasicMessageChannel<>(
                engine.getDartExecutor().getBinaryMessenger(),
                "dev.flutter.multiple-flutters",
                new StandardMessageCodec()
        );
    }

    public void attach() {
        mMessageChannel.setMessageHandler((message, reply) -> {
            CommonParams commonParams = CommonParams.fromMap((Map<String, Object>) message);
            String method = commonParams.getMethod();
            switch (method) {
                case "pushNativePage":
                    delegate.openNativePage(commonParams.getArguments());
                    break;
                case "getInitialRouteInfo": {
                    HashMap<String, Object> replyMap = new HashMap<>();
                    String initialRoute = delegate.getInitialRoute();
                    if (TextUtils.isEmpty(initialRoute)) {
                        initialRoute = "/";
                    }
                    HashMap<String, Object> result = new HashMap<>();
                    result.put("initialRoute", initialRoute);
                    result.put("arguments", "嗨，你好吗？");
                    replyMap.put("result", result);
                    reply.reply(replyMap);
                    break;
                }
                case "pop": {
                    delegate.pop(commonParams.getArguments());
                    break;
                }
            }
        });
    }

    public void detach() {
        mMessageChannel.setMessageHandler(null);
    }

    public void onNativeResult(Object result){
        if (mMessageChannel != null){
            Log.d(TAG, "onNativeResult: " + result.toString());
            CommonParams commonParams = new CommonParams();
            commonParams.setMethod("onNativeResult");
            if (result instanceof Map){
                Map<String, Object> resultMap = (Map<String, Object>) result;
                commonParams.setArguments(resultMap);
            }
            mMessageChannel.send(commonParams.toMap());
        }
    }

    public FlutterEngine getEngine() {
        return engine;
    }
}
